package com.yeyks.config;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.yeyks.common.appcommon.dto.account.AppAccountDTO;
import com.yeyks.common.appcommon.result.CommonAuthHeader;
import com.yeyks.common.appcommon.result.CommonResult;
import com.yeyks.common.appcommon.result.ThreadLocalUtil;
import com.yeyks.common.exception.OftenFiledException;
import com.yeyks.common.utils.apputil.bean.MyBeanUtils;
import com.yeyks.entity.AppAccountInfo;
import com.yeyks.service.AppAccountTokenService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.servlet.FilterConfig;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;

/**
 * 全局的过滤器
 *
 * @author: gui
 * @date: 2019/6/18 0018 11:10
 */
@WebFilter(filterName = "MyFilter", urlPatterns = "/*")
@Slf4j
public class AdminFilter implements Filter {

    @Autowired
    private AppAccountTokenService tokenService;

    @Autowired
    private PermitUrlConfiguration permitUrlConfiguration;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {


        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        if (!permitAllUrl(request, permitUrlConfiguration.getPermitUrlArray())) {

            //如果有些路径要鉴权的话，根据version判断就不怎么合理了。当强制更新所有的东西后， 在决定将version去掉。

            CommonAuthHeader commonAuthHeader = new CommonAuthHeader();
            Map<String, String> headerMap = getHeadersInfo(request);
            //如果版本为空,代表是老版本
            String version = headerMap.get("version");
            if (!StringUtils.isEmpty(version)) {
                if (!CollectionUtils.isEmpty(headerMap)) {
                    commonAuthHeader.setToken(headerMap.get("token"));
                    commonAuthHeader.setVersion(version);
                    commonAuthHeader.setPlatform(headerMap.get("platform"));
                }

                //验证token
                CommonResult<AppAccountInfo> availAccount = tokenService.getAvailAccount(commonAuthHeader.getToken(), commonAuthHeader.getVersion(), commonAuthHeader.getPlatform());
                if (null != availAccount && availAccount.getCode() != CommonResult.SUCCESS) {
                    //message中存入JSON，方便ErrorController拦截
                    throw new OftenFiledException(JSONObject.toJSONString(availAccount));
                }else{
                    assert availAccount != null;
                    ThreadLocalUtil.setAccount(MyBeanUtils.convert(availAccount.getData(), AppAccountDTO.class));
                }
            }
        }
        //想办法把账户信息存入 ThreadLocal, 进行相关的存储, 请求完成之后，清除当前线程
        chain.doFilter(request, response);
        ThreadLocalUtil.removeAccount();
    }

    @Override
    public void destroy() {

    }

    private boolean permitAllUrl(HttpServletRequest request, String[] permitUrlArray) {
        if (request == null) {
            return true;
        }
        log.info("请求地址为[{}]",request.getRequestURI());
        if (request.getMethod() != null && request.getMethod().toUpperCase().equals(HttpMethod.OPTIONS.name())) {
            return true;
        }
        if (null != permitUrlArray && permitUrlArray.length > 0) {
            for (String eachItem : permitUrlArray) {
                if (new AntPathMatcher().match(eachItem, request.getRequestURI())) {
                    return true;
                }
            }
        }
        return false;
    }

    public static Map<String, String> getHeadersInfo(HttpServletRequest request) {
        Map<String, String> map = Maps.newHashMap();
        Enumeration headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = (String) headerNames.nextElement();
            String value = request.getHeader(key);
            map.put(key, value);
        }
        return map;
    }
}
